/**
	Pulsar engine. Additional include file.
	Syncronisation classes

	Copyright (C) 2013-2014 Dmitry Dolgov

	This program is free software; you can redistribute it and/or modify it under the terms of the
	GNU General Public License as published by the Free Software Foundation; either version 2 of
	the License, or (at your option) any later version.
		
	This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
	without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
	See the GNU General Public License for more details.
*/

namespace pl
{

/// 
const pl_uint32 RESERVED_SIZE = 64;

class SemaphoreImpl;
class CriticalSectionImpl;

/// Semaphore
class Semaphore
{
public:
	/// Ctor
	Semaphore(pl_uint32 iniCount, pl_uint32 maxCount, const pl_char* name = NULL);

	/// Dtor
	~Semaphore();

	/// Release
	void release();

	/**
		Wait
		\param timeMs time in millisecond
		\return true - wait success, false - wait timeout
	*/
	bool wait(pl_int32 timeMs);

protected:
	/// Platform-specific
	pl_uint8 _reserved[RESERVED_SIZE];

private:
	/// Points to _reserved
	SemaphoreImpl* _pImpl;
};

/// Critical Section
class CriticalSection
{
public:
	/// Ctor
	CriticalSection(const pl_char* name = NULL);

	/// Dtor
	~CriticalSection();

	/// Entering
	void enter();

	/// Leaving
	void leave();

	/// Trying to enter
	bool tryEnter();

protected:
	/// Platform-specific
	pl_uint8 _reserved[RESERVED_SIZE];

private:
	/// Points to _reserved
	CriticalSectionImpl* _pImpl;
};

/// Critical section in ctor/dtor
class Lock
{
public:
	Lock(pl::CriticalSection *section) :
	_section(section)
	{
		_section->enter();
		return;
	}

	~Lock()
	{
		_section->leave();
		return;
	}

private:
	pl::CriticalSection *_section;
};

extern long interlockedIncrement(volatile long* value);
extern long interlockedDecrement(volatile long* value);

} // namespace pl

//
// End of file 'pulsar_syncronize.h'
//
